﻿using System;
using System.IO;
using System.Xml;

using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using FluentAssertions;

namespace CodeStream.Testing.WebAutomation.UnitTests
{
    [TestClass]
    public class UIMapUnitTests
    {
        [TestMethod]
        public void UIMap_Can_Parse_UIMap_Definition()
        {
            string uiDefinition =
                "<Page name=\"SamplePage\" xmlns=\"http://codestreamtech.com/Testing/WebAutomation/UIDefinition/2011/08\">" +
                  "<Control name=\"Root Container\" tag=\"div\" id=\"container\"> " + // lookup by id, contains control and container
                    "<Control name=\"Root Container Control\" tag=\"a\" class=\"root\" /> " + // lookup by class
                    "<Control name=\"Repeating Container\" tag=\"ul\" id=\"list\" multiple=\"true\" > " + // multiple container, contains multiple
                      "<Control name=\"Repeating Control\" tag=\"li\" multiple=\"true\" /> " + // lookup by tag, multiple
                    "</Control>" +
                  "</Control>" +
                  "<Control name=\"Root Control\" tag=\"span\" id=\"root\" />" + // root control, lookup by id
                "</Page>";

            UIDefinitionPage page = null;
            using (XmlReader reader = XmlReader.Create(new StringReader(uiDefinition)))
                page = UIDefinitionPage.Create(reader);

            page.Name.Should().Be("SamplePage");
            page.Containers.Should().HaveCount(2, "there should be two children in the sample page");
            page.Fields.Should().HaveCount(2, "there should be one control in the sample page");
            page.Fields[0].ShouldBe("Root_Container", "div", "container", null, "Root_Container");
            page.Fields[1].ShouldBe("Root_Control", "span", "root", null, typeof(HtmlSpan));

            // verify the root container
            UIDefinitionClass rootContainer = page.Containers[0];
            rootContainer.ShouldBe("Root_Container", "div", "container", null, typeof(HtmlDiv));
            rootContainer.Fields.Should().HaveCount(2, "there should be two fields in the root container");
            rootContainer.Fields[0].ShouldBe("Root_Container_Control", "a", null, "root", typeof(HtmlHyperlink));
            rootContainer.Fields[1].ShouldBe("Repeating_Container", "ul", "list", null, "Root_Container_Repeating_Container", true);

            // verify the repeating container
            UIDefinitionClass repeatingContainer = page.Containers[1];
            repeatingContainer.ShouldBe("Root_Container_Repeating_Container", "ul", "list", null, typeof(HtmlCustom));
            repeatingContainer.Fields.Should().HaveCount(1, "there should be one field in the repeating container");
            repeatingContainer.Fields[0].ShouldBe("Repeating_Control", "li", null, null, typeof(HtmlCustom), true);
        }

        [TestMethod]
        public void UIMap_Can_Detect_Invalid_UIMap_Definition()
        {
           string uiDefinition =
               "<Page name=\"SamplePage\" xmlns=\"http://codestreamtech.com/Testing/WebAutomation/UIDefinition/2011/08\">" +
                 "<Control name=\"Root #Container\" tag=\"div\" id=\"container\"> " + // lookup by id, contains control and container
                   "<Control name=\"Root Container Control\" tag=\"\" class=\"root\" multiple=\"false\" /> " + // lookup by class
                   "<Control name=\"Repeating Container\" tag=\"ul\" id=\"list\" multiple=\"true\" > " + // multiple container, contains multiple
                     "<Control name=\"Repeating Control\" tag=\"li\" multiple=\"true\" /> " + // lookup by tag, multiple
                   "</Control>" +
                 "</Control>" +
                 "<Invalid />" +
                 "<Control tag=\"span\" id=\"root\" />" + // root control, lookup by id
               "</Page>";
            
            try
            {
                using (XmlReader reader = XmlReader.Create(new StringReader(uiDefinition)))
                    UIDefinitionPage.Create(reader);

                Assert.Fail("Expected the creation of the UIDefinitionPage to fail due to schema errors");
            }
            catch (AggregateException)
            {                
            }
        }

        [TestMethod]
        public void UIMap_Can_Handle_Duplicate_Container_Names()
        {
            string uiDefinition = 
                "<Page name=\"DuplicatePage\" xmlns=\"http://codestreamtech.com/Testing/WebAutomation/UIDefinition/2011/08\">" +
                  "<Control name=\"RootOne\" tag=\"div\" id=\"container1\"> " +
                    "<Control name=\"Child\" tag=\"ul\" id=\"list\" > " +
                      "<Control name=\"Control\" tag=\"li\" multiple=\"true\" /> " +
                    "</Control>" +
                  "</Control>" +
                  "<Control name=\"RootTwo\" tag=\"div\" id=\"container2\"> " +
                    "<Control name=\"Child\" tag=\"ul\" id=\"list\" > " +
                      "<Control name=\"Control\" tag=\"li\" multiple=\"true\" /> " +
                    "</Control>" +
                  "</Control>" +
                "</Page>";

            UIDefinitionPage page = null;
            using (XmlReader reader = XmlReader.Create(new StringReader(uiDefinition)))
                page = UIDefinitionPage.Create(reader);

            page.Name.Should().Be("DuplicatePage");
            page.Containers.Should().HaveCount(4, "there should be two children in the page");

            UIDefinitionClass rootOne = page.Containers[0];
            rootOne.ShouldBe("RootOne", "div", "container1", null, typeof(HtmlDiv));
            rootOne.Fields.Should().HaveCount(1, "there should be one field in the RootOne container");
            rootOne.Fields[0].ShouldBe("Child", "ul", "list", null, "RootOne_Child");

            UIDefinitionClass child1 = page.Containers[1];
            child1.ShouldBe("RootOne_Child", "ul", "list", null, typeof(HtmlCustom));
            child1.Fields.Should().HaveCount(1, "there should be one field in the Child container");
            child1.Fields[0].ShouldBe("Control", "li", null, null, typeof(HtmlCustom), true);

            UIDefinitionClass rootTwo = page.Containers[2];
            rootTwo.ShouldBe("RootTwo", "div", "container2", null, typeof(HtmlDiv));
            rootTwo.Fields.Should().HaveCount(1, "there should be one field in the RootTwo container");
            rootTwo.Fields[0].ShouldBe("Child", "ul", "list", null, "RootTwo_Child");

            UIDefinitionClass child2 = page.Containers[3];
            child2.ShouldBe("RootTwo_Child", "ul", "list", null, typeof(HtmlCustom));
            child2.Fields.Should().HaveCount(1, "there should be one field in the Child container");
            child2.Fields[0].ShouldBe("Control", "li", null, null, typeof(HtmlCustom), true);
        }
    }
}
